package org.grayrabbit.cloud.core.module;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.commons.lang.StringUtils;
import org.grayrabbit.cloud.core.biz.BizAbstractModule;
import org.grayrabbit.cloud.core.biz.BizArgument;
import org.grayrabbit.cloud.core.biz.BizResult;
import org.grayrabbit.cloud.core.biz.ServerUtility;
import org.grayrabbit.cloud.core.config.ConfiguratorException;
import org.grayrabbit.cloud.core.rpc.Argument;
import org.grayrabbit.cloud.core.rpc.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class SpringModule extends BizAbstractModule {
	private ApplicationContext appContext;
	private static Logger logger = LoggerFactory.getLogger(SpringModule.class);

	public Result submit(Argument argument) throws ModuleException {
		if (argument instanceof BizArgument) {
			BizArgument arg = (BizArgument) argument;
			String id = getInstanceName(arg);
			String methodName = getMethodName(arg);
			logger.debug("instance id:{}", id);
			Object bean = appContext.getBean(id);
			try {
				Method method = bean.getClass().getMethod(methodName, arg.getParamTypes());
				Object result = method.invoke(bean, arg.getParams());
				return BizResult.create(result);
			} catch (SecurityException e) {
				throw new ModuleException(e);
			} catch (NoSuchMethodException e) {
				throw new ModuleException(e);
			} catch (IllegalArgumentException e) {
				throw new ModuleException(e);
			} catch (IllegalAccessException e) {
				throw new ModuleException(e);
			} catch (InvocationTargetException e) {
				throw new ModuleException(e);
			}
		}
		return BizResult.NULL;
	}

	@Override
	public void construct(String name) throws ModuleConstructException {
		super.construct(name);
		try {
			String defaultName = "applictionContext.xml";
			String config = ServerUtility.getProperty("module", name, "config");
			if (StringUtils.isNotBlank(config)) {
				defaultName = config;
			}
			if(SpringContextUtil.WEB_APPLICATION_KEY.equalsIgnoreCase(defaultName)){
				appContext = SpringContextUtil.newInstance().getValue(SpringContextUtil.WEB_APPLICATION_KEY);
			}else{
				appContext = new ClassPathXmlApplicationContext("classpath*:**/*"+defaultName);
			}
			appContext.getBean("sessionFactory");
		} catch (ConfiguratorException e) {
			throw new ModuleConstructException(e);
		}
	}

	private String getInstanceName(BizArgument argument) {
		return argument.getCmdParams().get("bean");
	}

	private String getMethodName(BizArgument argument) {
		return argument.getCmdParams().get("method");
	}
}
